home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfscheck / lfscheck.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-12  |  58.0 KB  |  1,963 lines

  1. /* 
  2.  * lfscheck.c --
  3.  *
  4.  *    The lfscheck program - Check an LFS file system to make sure it
  5.  *    is consistent.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /user2/mendel/lfs/src/cmds/checkLfs/RCS/checkLfs.c,v 1.1 90/06/01 10:10:18 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #ifdef __STDC__
  22. #define _HAS_PROTOTYPES
  23. #endif
  24.  
  25. #include <cfuncproto.h>
  26. #ifdef _HAS_PROTOTYPES
  27. #include <varargs.h>
  28. #endif
  29. #include <sprite.h>
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <option.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/file.h>
  36. #include <alloca.h>
  37. #include <bstring.h>
  38. #include <unistd.h>
  39. #include <bit.h>
  40. #include <time.h>
  41. #include <sys/time.h>
  42. #include <fs.h>
  43. #include <kernel/fs.h>
  44. #include <kernel/dev.h>
  45. #include <kernel/fsdm.h>
  46. #include <kernel/fslcl.h>
  47. #include <kernel/devDiskLabel.h>
  48.  
  49. #include <kernel/lfsDesc.h>
  50. #include <kernel/lfsDescMap.h>
  51. #include <kernel/lfsFileLayout.h>
  52. #include <kernel/lfsDirOpLog.h>
  53. #include <kernel/lfsSegLayout.h>
  54. #include <kernel/lfsStableMem.h>
  55. #include <kernel/lfsSuperBlock.h>
  56. #include <kernel/lfsUsageArray.h>
  57. #include <kernel/lfsStats.h>
  58.  
  59. #include "fscheck.h"
  60.  
  61.  
  62. /*
  63.  * The super block of the file system.
  64.  */
  65. LfsSuperBlock    *superBlockPtr;
  66.  
  67. /*
  68.  * The descriptor map and segment usage array of file system.
  69.  */
  70. ClientData descMapDataPtr;        /* Descriptor map of file system. */
  71. LfsDescMapCheckPoint *descMapCheckPointPtr; /* Most current descriptor map 
  72.                          * check point. */
  73. FdInfo        *descInfoArray;
  74.  
  75. ClientData   usageArrayDataPtr;    /* Data of usage map. */
  76.  
  77.  
  78. typedef struct Seg {
  79.     int      segNo;    /* Segment number. */
  80.     int      segSizeInBlocks;    /* Segment size in blocks. */
  81.     int   diskFd;        /* Open file of disk. */
  82. } Seg;
  83.  
  84. /*
  85.  * Info kept for each block in the file system while running in full check
  86.  * mode. We use bit fields to keep the size down.
  87.  */
  88.  
  89. typedef struct BlockInfo {
  90.     int        type :8;    /* Type of block. See defines below. */
  91.     int     found:1;    /* TRUE if found in summary region. */
  92.     int         :3;
  93.     int     blockNum:20; /* Block number of block's owner. */
  94.     int     fileNum;    /* File number of block's owner. */
  95. } BlockInfo;
  96. /*
  97.  * Block info types. 
  98.  *    UNUSED    - Not allocated.
  99.  *    FILE    - Owned by a file. FileNum and blockNum specify the file
  100.  *          and block.
  101.  *    DESC_MAP - A block of the descriptor map. BlockNum specifies the block.
  102.  *    USAGE_ARRAY - A block of the segment usage array.
  103.  *    SUMMARY        - Block is a summary block.
  104.  *    CHECKPOINT  - Block is a checkpoint block.
  105.  *    DESC        - Block contains file descriptors.
  106.  *    DIRLOG        - Directory log block
  107.  */
  108. #define    UNUSED    0
  109. #define    FILE    1
  110. #define    DESC_MAP 2
  111. #define USAGE_ARRAY 3
  112. #define    SUMMARY        4
  113. #define CHECKPOINT  5
  114. #define    DESC       6
  115. #define    DIRLOG        7
  116. #define    UNKNOWN   8
  117.  
  118. char    *blockTypeNames[UNKNOWN+1] = { 
  119.     "Unused", "File", "DescMap" , "UsageArray", "Summary", "Checkpoint",
  120.     "Descriptor", "DirLog", "Unknown" 
  121. };
  122.  
  123. BlockInfo    *blockInfoArray;  /* BlockInfo for each block in fs. */
  124. int        *usageBitMap;      /* Bit map of block usage during quick check
  125.                    * of file system. */
  126. int        *foundBitMap;      /* Bit map of block found during summary
  127.                    * check. */
  128. int        *descBlockBitMap;      /* Bit map of desc blocks. */
  129. int        numBlocks;      /* Number of blocks in fs. */
  130.  
  131. int    *activeBytesArray;    /* Computed active bytes for each segment. */
  132.  
  133. int    minorErrors;
  134. int    majorErrors;
  135.  
  136. /*
  137.  * Arguments.
  138.  */
  139. int    blockSize = 512;    /* File system block size. */
  140. int    superBlockOffset = 64;    /* Offset of super block. */
  141. Boolean dumpFlag = FALSE;    /* Dump version description of file system. */
  142. Boolean showDirLog = FALSE;    /* Show the directory log. */
  143. Boolean    verboseFlag = FALSE;    /* Trace progress of program. */
  144. char    *deviceName;        /* Device to use. */
  145. Boolean    full = FALSE;
  146. Boolean oldcp = FALSE;
  147. Option optionArray[] = {
  148.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  149.     "Check a LFS file system and report problems.\n Synopsis: \"checkLfs [switches] deviceName\"\n Command-line switches are:"},
  150.     {OPT_INT, "blockSize", (Address) &blockSize, 
  151.     "Block size of file system."},
  152.     {OPT_INT, "superBlockOffset", (Address) &superBlockOffset, 
  153.     "Offset into device of the superBlock."},
  154.     {OPT_TRUE, "dump", (Address) &dumpFlag, 
  155.     "Print out a description of file system."},
  156.     {OPT_TRUE, "showDirLog", (Address) &showDirLog, 
  157.     "Print out the directory operation log."},
  158.     {OPT_TRUE, "full", (Address) &full, 
  159.     "Full a full error analysis."},
  160.     {OPT_TRUE, "verbose", (Address) &verboseFlag, 
  161.     "Output progress messages during execution."},
  162.     {OPT_TRUE, "oldcp", (Address) &oldcp, 
  163.     "Output progress messages during execution."},
  164. };
  165. /*
  166.  * Forward routine declartions.
  167.  */
  168. extern Boolean LoadUsageArray _ARGS_((int diskFd, int checkPointSize, 
  169.             char *checkPointPtr));
  170. extern Boolean LoadDescMap _ARGS_((int diskFd, int checkPointSize,
  171.             char *checkPointPtr));
  172. extern char *GetUsageState _ARGS_((LfsSegUsageEntry *entryPtr));
  173. static void CheckAllFiles _ARGS_((int diskFd));
  174. static void CheckFile _ARGS_((int diskFd, int fileNum,             
  175.             LfsFileDescriptor *descPtr));
  176. static void CheckIndirectBlock _ARGS_((int diskFd, int fileNum, 
  177.         LfsFileDescriptor *descPtr, int blockNum, int blockAddress));
  178. static void CheckBlock _ARGS_((int diskFd, int fileNum, 
  179.         LfsFileDescriptor *descPtr, int blockNum, int blockAddress));
  180. static void CheckUsageArray _ARGS_((int diskFd));
  181. static void CheckSummaryRegions _ARGS_((int diskFd));
  182. static void CheckSegUsageSummary _ARGS_((int diskFd, Seg *segPtr,
  183.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  184. static void CheckDescMapSummary _ARGS_((int diskFd, Seg *segPtr, 
  185.     int startAddress, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  186. static void CheckFileLayoutSummary _ARGS_((int diskFd, Seg *segPtr,
  187.     int startAddr, int offset, LfsSegSummaryHdr *segSummaryHdrPtr));
  188. static char *GetOwner _ARGS_((int blockNum));
  189. static void PrintSuperBlock _ARGS_((LfsSuperBlock *superBlockPtr));
  190. static void PrintCheckPointHdr _ARGS_((LfsCheckPointHdr *headerPtr, int region));
  191. static ClientData LoadStableMem _ARGS_((int diskFd, LfsStableMemParams *smemParamsPtr, LfsStableMemCheckPoint *cpPtr, int type));
  192. static int GetStableMemBlockIndex _ARGS_((ClientData clientData, int blockNum));
  193. static void ShowDirLogBlock _ARGS_((LfsDirOpLogBlockHdr *hdrPtr, int addr));
  194.  
  195. static char *FmtTime _ARGS_((void));
  196. static Seg *SegInit _ARGS_((int diskFd, int segNumber));
  197. static int SegStartAddr _ARGS_((Seg *segPtr));
  198. static char *SegFetchBlock _ARGS_((Seg *segPtr, int blockOffset, int size));
  199. static void SegReleaseBlock _ARGS_((Seg *segPtr, char *memPtr));
  200. static void SegRelease _ARGS_((Seg *segPtr));
  201.  
  202. extern int open();
  203. extern void panic();
  204. extern int gettimeofday _ARGS_((struct timeval *tp, struct timezone *tzp));
  205.  
  206. /*
  207.  *----------------------------------------------------------------------
  208.  *
  209.  * main --
  210.  *
  211.  *    Main routine of checklfs - parse arguments and do the work.
  212.  *
  213.  * Results:
  214.  *    None.
  215.  *
  216.  * Side effects:
  217.  *    None.
  218.  *
  219.  *----------------------------------------------------------------------
  220.  */
  221.  
  222. int
  223. main(argc,argv)
  224.     int    argc;
  225.     char *argv[];
  226. {
  227.     int       diskFd, maxCheckPointSize;
  228.     LfsCheckPointHdr    checkPointHdr[2], *checkPointHdrPtr;
  229.     char        *checkPointPtr, *trailerPtr;
  230.     LfsCheckPointRegion *regionPtr;
  231.     LfsCheckPointTrailer *trailPtr;
  232.     int            choosenOne, i;
  233.  
  234.  
  235.  
  236.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  237.     if (argc != 2) { 
  238.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  239.      exit(EXIT_BAD_ARG);
  240.     } else {
  241.     deviceName = argv[1];
  242.     }
  243.     diskFd = open(deviceName, O_RDONLY, 0);
  244.     if (diskFd < 0) {
  245.     fprintf(stderr,"%s:", argv[0]);
  246.     perror(deviceName);
  247.     exit(EXIT_HARD_ERROR);
  248.     }
  249.     /*
  250.      * Fill in the super block header.
  251.      */
  252.     superBlockPtr = (LfsSuperBlock *) malloc(LFS_SUPER_BLOCK_SIZE);
  253.     if (DiskRead(diskFd, superBlockOffset, sizeof(LfsSuperBlock), 
  254.         (char *)superBlockPtr) != sizeof(LfsSuperBlock)) {
  255.     fprintf(stderr,"%s:Can't read superblock.\n", deviceName);
  256.     exit(EXIT_READ_FAILURE);
  257.  
  258.     }
  259.     if (superBlockPtr->hdr.magic != LFS_SUPER_BLOCK_MAGIC) {
  260.     fprintf(stderr,"%s:Bad magic number for filesystem\n", deviceName);
  261.     exit(EXIT_READ_FAILURE);
  262.     }
  263.     if (dumpFlag) {
  264.        PrintSuperBlock(superBlockPtr);
  265.     }
  266.  
  267.     /*
  268.      * Examine the two checkpoint areas to locate the checkpoint area with the
  269.      * newest timestamp.
  270.      */
  271.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[0],
  272.         sizeof(LfsCheckPointHdr), (char *) (checkPointHdr+0)) != 
  273.     sizeof(LfsCheckPointHdr)) {
  274.     fprintf(stderr,"%s:Can't read checkPointHeader 0.\n", deviceName);
  275.     checkPointHdr[0].timestamp = 0;
  276.     }
  277.     if (dumpFlag) {
  278.     PrintCheckPointHdr(checkPointHdr, 0);
  279.     }
  280.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[1],
  281.         sizeof(LfsCheckPointHdr), (char *) (checkPointHdr+1))  != 
  282.     sizeof(LfsCheckPointHdr)) {
  283.     fprintf(stderr,"%s:Can't read checkPointHeader 1.\n", deviceName);
  284.     checkPointHdr[1].timestamp = 0;
  285.     }
  286.     if ((checkPointHdr[0].timestamp == 0) &&
  287.     (checkPointHdr[1].timestamp == 0)) {
  288.     fprintf(stderr,"%s:Can't read either checkPointHeader.\n", deviceName);
  289.     exit(EXIT_READ_FAILURE);
  290.     }
  291.     if (dumpFlag) {
  292.     PrintCheckPointHdr(checkPointHdr+1, 1);
  293.     }
  294.  
  295.     choosenOne = (checkPointHdr[0].timestamp<checkPointHdr[1].timestamp) ?
  296.                 1 : 0;
  297.  
  298.     if (oldcp) {
  299.     choosenOne = !choosenOne;
  300.     }
  301.     maxCheckPointSize = superBlockPtr->hdr.maxCheckPointBlocks * 
  302.                 blockSize;
  303.     checkPointPtr = malloc(maxCheckPointSize);
  304.     if (verboseFlag) {
  305.     printf("%s:Read LFS checkpoint from %s\n", FmtTime(), deviceName);
  306.     }
  307.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[choosenOne],
  308.         maxCheckPointSize, checkPointPtr) != maxCheckPointSize) {
  309.     fprintf(stderr,"%s:Can't read checkPoint %d\n", deviceName, choosenOne);
  310.     exit(EXIT_READ_FAILURE);
  311.     }
  312.  
  313.  
  314.     checkPointHdrPtr = (LfsCheckPointHdr *) checkPointPtr;
  315.     trailerPtr = (checkPointPtr + checkPointHdrPtr->size - 
  316.                 sizeof(LfsCheckPointTrailer));
  317.     trailPtr = (LfsCheckPointTrailer *) trailerPtr;
  318.     if (trailPtr->timestamp != checkPointHdrPtr->timestamp) {
  319.     fprintf(stderr,"%s:Header timestamp %d doesn't match trailer timestamp %d\n", deviceName, checkPointHdrPtr->timestamp, trailPtr->timestamp);
  320.     minorErrors++;
  321.     }
  322.     if (dumpFlag) {
  323.     printf("Using checkpoint area %d with timestamp %d domain %d (%s)\n",
  324.         choosenOne, checkPointHdrPtr->timestamp, 
  325.         checkPointHdrPtr->domainNumber, checkPointHdrPtr->domainPrefix);
  326.     }
  327.  
  328.     checkPointPtr = checkPointPtr + sizeof(LfsCheckPointHdr);
  329.  
  330.     numBlocks = superBlockPtr->usageArray.numberSegments * 
  331.                 (superBlockPtr->usageArray.segmentSize/blockSize) +
  332.                 superBlockPtr->hdr.logStartOffset;
  333.     if (full) {
  334.     /*
  335.      * Allocate the blockInfoArray for the file system. Zero 
  336.      * marks all blocks as UNUSED.
  337.      */
  338.     blockInfoArray = (BlockInfo *) calloc(numBlocks, sizeof(BlockInfo));
  339.     } else {
  340.     /*
  341.      * Allocate the block usage bitmap.
  342.      */
  343.     Bit_Alloc(numBlocks, usageBitMap);
  344.     Bit_Alloc(numBlocks, descBlockBitMap);
  345.     }
  346.     /*
  347.      * Allocate the descriptor found array. Zero marks all descriptors
  348.      * as unallocated.
  349.      */
  350.     descInfoArray = (FdInfo *) calloc(superBlockPtr->descMap.maxDesc, 
  351.                     sizeof(FdInfo));
  352.  
  353.     /*
  354.      * Allocate the real active bytes array. Initialize each entry to zero
  355.      * bytes used.
  356.      */
  357.     activeBytesArray = (int *) calloc(superBlockPtr->usageArray.numberSegments,
  358.                     sizeof(activeBytesArray[0]));
  359.     /*
  360.      * Mark blocks upto log start as checkpoint blocks.
  361.      */
  362.     for (i = 0; i < superBlockPtr->hdr.logStartOffset; i++) {
  363.     if (full) { 
  364.         blockInfoArray[i].type = CHECKPOINT;
  365.         blockInfoArray[i].found = TRUE;
  366.     } else {
  367.         Bit_Set(i, usageBitMap);
  368.     }
  369.     }
  370.     /*
  371.      * Load the LFS metadata from the last checkpoint.
  372.      */
  373.     while (checkPointPtr < trailerPtr) { 
  374.     regionPtr = (LfsCheckPointRegion *) checkPointPtr;
  375.     if (regionPtr->size == 0) {
  376.         break;
  377.     }
  378.     switch (regionPtr->type) {
  379.     case LFS_SEG_USAGE_MOD:
  380.         LoadUsageArray(diskFd, regionPtr->size - sizeof(*regionPtr),
  381.                 (char *) (regionPtr+1));
  382.         break;
  383.     case LFS_DESC_MAP_MOD:
  384.         LoadDescMap(diskFd, regionPtr->size - sizeof(*regionPtr),
  385.                 (char *) (regionPtr+1));
  386.         break;
  387.     case LFS_FILE_LAYOUT_MOD:
  388.         if (regionPtr->size != sizeof(*regionPtr)) {
  389.         minorErrors++;
  390.         fprintf(stderr,"%s:Bad size %d for FILE_LAYOUT checkpoint\n",
  391.                 deviceName,regionPtr->size);
  392.         }
  393.         break;
  394.     default: {
  395.         minorErrors++;
  396.         fprintf(stderr,"%s:Unknown region type %d of size %d\n",
  397.             deviceName,
  398.             regionPtr->type, regionPtr->size);
  399.         break;
  400.         }
  401.     }
  402.     checkPointPtr += regionPtr->size;
  403.     }
  404.  
  405.     if (verboseFlag) {
  406.     printf("%s:Checking files\n", FmtTime());
  407.     }
  408.     CheckAllFiles(diskFd);
  409.     if (verboseFlag) {
  410.     printf("%s:Checking usage array\n",FmtTime());
  411.     }
  412.     CheckUsageArray(diskFd);
  413.     if (verboseFlag) {
  414.     printf("%s:Checking directory tree\n",FmtTime());
  415.     }
  416.     CheckDirTree(diskFd);
  417.  
  418.     if (verboseFlag) {
  419.     printf("%s:Checking summary regions\n", FmtTime());
  420.     }
  421.     if (!full) { 
  422.     foundBitMap = descBlockBitMap;
  423.     Bit_Zero(numBlocks, foundBitMap);
  424.     for (i = 0; i < superBlockPtr->hdr.logStartOffset; i++) {
  425.         Bit_Set(i, foundBitMap);
  426.     }
  427.     }
  428.     CheckSummaryRegions(diskFd);
  429.  
  430.     /*
  431.      * Report any block that was pointed to by something but to described
  432.      * by that's block summary info.
  433.      */
  434.  
  435.     if (verboseFlag) {
  436.     printf("%s:Reporting errors\n", FmtTime());
  437.     }
  438.     for (i = 0; i < numBlocks; i++) {
  439.     if (full) { 
  440.         if ((blockInfoArray[i].type != UNUSED) && !blockInfoArray[i].found) {
  441.          majorErrors++;
  442.         fprintf(stderr,"%s:No summary region for block at %d own by %s\n",
  443.                 deviceName, i, GetOwner(i));
  444.         }
  445.     } else {
  446.         if (Bit_IsSet(i, usageBitMap) && Bit_IsClear(i, foundBitMap)) {
  447.         majorErrors++;
  448.         fprintf(stderr,"%s:No summary region for in use block at %d\n",
  449.                 deviceName, i);
  450.         }
  451.  
  452.     }
  453.  
  454.     }
  455.     /*
  456.      * Report any desc allocated but not described by a summary block.
  457.      */
  458.     for (i = 2; i < superBlockPtr->descMap.maxDesc; i++) {
  459.     LfsDescMapEntry *descMapPtr;
  460.     descMapPtr = DescMapEntry(i);
  461.     if ((descMapPtr->flags == LFS_DESC_MAP_ALLOCED) &&
  462.         !(descInfoArray[i].flags & FD_ALLOCATED)) {
  463.         majorErrors++;
  464.         fprintf(stderr,"%s:No summary region for desc %d; should be a %d\n",
  465.             deviceName, i, descMapPtr->blockAddress);
  466.     }
  467.     }
  468.     if (majorErrors + minorErrors > 0) {
  469.     printf("%s: %d major errors %d minor errors\n", deviceName, 
  470.         majorErrors, minorErrors);
  471.     if (majorErrors > 0) {
  472.         exit(EXIT_HARD_ERROR);
  473.     } 
  474.     }
  475.     exit(EXIT_OK);
  476.     return EXIT_OK;
  477. }
  478.  
  479. /*
  480.  *----------------------------------------------------------------------
  481.  *
  482.  * LoadUsageArray --
  483.  *
  484.  *    Load the segment usage array into memory.
  485.  *
  486.  * Results:
  487.  *    TRUE if array can be loaded. FALSE otherwise.
  488.  *
  489.  * Side effects:
  490.  *    None.
  491.  *
  492.  *----------------------------------------------------------------------
  493.  */
  494.  
  495. Boolean
  496. LoadUsageArray(diskFd, checkPointSize, checkPointPtr)
  497.     int    diskFd;        /* File descriptor of disk. */
  498.     int    checkPointSize; /* Size of the checkpoint region. */
  499.     char *checkPointPtr; /* The checkpoint region. */
  500. {
  501.     LfsSegUsageParams    *usagePtr;
  502.     LfsSegUsageCheckPoint    *cp;
  503.     LfsSegUsageEntry        *entryPtr;
  504.     LfsStableMemCheckPoint *cpPtr;
  505.     LfsStableMemParams  *smemParamsPtr;
  506.     int    i, numClean,  numDirty, numFull, freeBlocks;
  507.     Boolean ret = TRUE;
  508.  
  509.     usagePtr = &(superBlockPtr->usageArray);
  510.     smemParamsPtr = &(superBlockPtr->usageArray.stableMem);
  511.  
  512.     cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  513.      cpPtr = (LfsStableMemCheckPoint *)
  514.             (checkPointPtr + sizeof(LfsSegUsageCheckPoint));
  515.  
  516.     if (dumpFlag) { 
  517.     printf("NumClean segments %d (%3.1f%%) NumDirty %d (%3.1f%%)\n",
  518.     cp->numClean, 
  519.     100.0*cp->numClean/(double)usagePtr->numberSegments,
  520.     cp->numDirty,
  521.     100.0*cp->numDirty/(double)usagePtr->numberSegments);
  522.  
  523.     printf("FreeBlocks %d (%3.1f%%) dirtyActiveBytes %d (%3.1f%%)\ncurrentSegment %d currentBlockOffset %d curSegActiveBytes %d\npreviousSegment %d cleanSegList %d\n",
  524.     cp->freeBlocks, 
  525.     100.0*cp->freeBlocks/ (double) numBlocks,
  526.     cp->dirtyActiveBytes, 
  527.     100.0*cp->dirtyActiveBytes/(double)usagePtr->segmentSize,
  528.     cp->currentSegment, cp->currentBlockOffset, cp->curSegActiveBytes,
  529.     cp->previousSegment, cp->cleanSegList);
  530.     }
  531.  
  532.     usageArrayDataPtr =  LoadStableMem(diskFd, smemParamsPtr, cpPtr, 
  533.             USAGE_ARRAY);
  534.     entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(cp->currentSegment);
  535.     entryPtr->activeBytes = cp->curSegActiveBytes;
  536.     if (entryPtr->activeBytes <= cp->dirtyActiveBytes) {
  537.     entryPtr->flags = LFS_SEG_USAGE_DIRTY;
  538.     }
  539.    if (dumpFlag) { 
  540.     for (i = 0; i < usagePtr->numberSegments; i++) {
  541.         entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(i);
  542.         printf("SegNum %d activeBytes %d state %s\n", 
  543.             i, entryPtr->activeBytes,
  544.             GetUsageState(entryPtr));
  545.     }
  546.     }
  547.     freeBlocks = 0;
  548.     numClean = numDirty = numFull = 0;
  549.     for (i = 0; i < usagePtr->numberSegments; i++) {
  550.     int bytes;
  551.     entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(i);
  552.     bytes =  ((entryPtr->flags & LFS_SEG_USAGE_CLEAN) ? 0 :
  553.                 entryPtr->activeBytes);
  554.     bytes = usagePtr->segmentSize - bytes;
  555.     freeBlocks += (bytes + blockSize - 1)/blockSize;
  556.     if (entryPtr->flags == LFS_SEG_USAGE_CLEAN) {
  557.         numClean++;
  558.     } else if (entryPtr->flags == LFS_SEG_USAGE_DIRTY) {
  559.         numDirty++;
  560.         if (entryPtr->activeBytes > cp->dirtyActiveBytes) {
  561.         minorErrors++;
  562.            fprintf(stderr, 
  563.        "%s:UsageArray: segment %d is marked dirty with activeBytes of %d\n",
  564.             deviceName,i, entryPtr->activeBytes);
  565.         }
  566.     } else if (entryPtr->flags == 0) {
  567.         numFull++;
  568.         if (entryPtr->activeBytes < cp->dirtyActiveBytes) {
  569.         minorErrors++;
  570.            fprintf(stderr, 
  571.        "%s:UsageArray: segment %d is marked full with activeBytes of %d\n",
  572.             deviceName,i, entryPtr->activeBytes);
  573.         }
  574.     } else {
  575.         numFull++;
  576.         minorErrors++;
  577.            fprintf(stderr, 
  578.            "%s:UsageArray: segment %d has unknown flags of 0x%x\n",
  579.             deviceName, i, entryPtr->flags);
  580.     }
  581.     if (entryPtr->flags != LFS_SEG_USAGE_CLEAN) {
  582.         if ((entryPtr->activeBytes < 0) ||
  583.         (entryPtr->activeBytes > usagePtr->segmentSize)) {
  584.            majorErrors++;
  585.            fprintf(stderr, 
  586.            "%s:UsageArray: segment %d has bad activeBytes of %d\n",
  587.                 deviceName, i, entryPtr->activeBytes);
  588.         }
  589.     }
  590.     }
  591.     if (numClean != cp->numClean) {
  592.     minorErrors++;
  593.     fprintf(stderr,"%s:UsageArray: Clean count wrong; is %d should be %d\n",
  594.             deviceName, cp->numClean, numClean);
  595.  
  596.     }
  597.     if (numDirty != cp->numDirty) {
  598.     minorErrors++;
  599.     fprintf(stderr,"%s:UsageArray: Dirty count wrong; is %d should be %d\n",
  600.             deviceName, cp->numDirty, numDirty);
  601.  
  602.     }
  603.     if (freeBlocks != cp->freeBlocks) {
  604.     minorErrors++;
  605.     fprintf(stderr,"%s:UsageArray: FreeBlocks wrong; is %d should be %d\n",
  606.             deviceName, cp->freeBlocks, freeBlocks);
  607.     }
  608.    return ret;
  609. }
  610.  
  611.  
  612. /*
  613.  *----------------------------------------------------------------------
  614.  *
  615.  * LoadDescMap --
  616.  *
  617.  *    Load the descriptor map array into memory.
  618.  *
  619.  * Results:
  620.  *    None.
  621.  *
  622.  * Side effects:
  623.  *    None.
  624.  *
  625.  *----------------------------------------------------------------------
  626.  */
  627. Boolean 
  628. LoadDescMap(diskFd, checkPointSize, checkPointPtr)
  629.     int    diskFd;        /* File descriptor of disk. */
  630.     int    checkPointSize; /* Size of the checkpoint region. */
  631.     char *checkPointPtr; /* The checkpoint region. */
  632. {
  633.     LfsDescMapParams    *descMapParamsPtr;
  634.     LfsDescMapEntry    *descMapPtr;
  635.     LfsDescMapCheckPoint    *cp;
  636.     int                i;
  637.     LfsStableMemCheckPoint *cpPtr;
  638.     int            numAlloced;
  639.     LfsStableMemParams  *smemParamsPtr;
  640.    Boolean         ret = TRUE;
  641.  
  642.     descMapParamsPtr = &(superBlockPtr->descMap);
  643.     smemParamsPtr = &(superBlockPtr->descMap.stableMem);
  644.  
  645.  
  646.     descMapCheckPointPtr = cp = (LfsDescMapCheckPoint *) checkPointPtr;
  647.  
  648.      cpPtr = (LfsStableMemCheckPoint *)
  649.             (checkPointPtr + sizeof(LfsDescMapCheckPoint));
  650.  
  651.     descMapDataPtr =  LoadStableMem(diskFd, smemParamsPtr, cpPtr, DESC_MAP);
  652.  
  653.     if (dumpFlag) { 
  654.     printf("DescMap num allocated: %d\n", cp->numAllocDesc);
  655.     for (i = 0; i < superBlockPtr->descMap.maxDesc; i++) {
  656.         descMapPtr = DescMapEntry(i);
  657.         if (descMapPtr->flags == LFS_DESC_MAP_ALLOCED) { 
  658.         printf("File %d at %d (seg %d) version %d flags %d\n", 
  659.                 i, descMapPtr->blockAddress, 
  660.                 descMapPtr->blockAddress/
  661.                 (superBlockPtr->usageArray.segmentSize/blockSize),
  662.                 descMapPtr->truncVersion,
  663.                 descMapPtr->flags);
  664.         }
  665.     }
  666.     }
  667.     numAlloced = 0;
  668.     for (i = 0; i < descMapParamsPtr->maxDesc; i++) {
  669.     descMapPtr = DescMapEntry(i);
  670.     if (descMapPtr->flags == LFS_DESC_MAP_ALLOCED) {
  671.         numAlloced++;
  672.     } else if (descMapPtr->flags != 0) {
  673.         minorErrors++;
  674.         fprintf(stderr,"%s:Unknowned desc map flags (0x%x) for file %d\n",
  675.             deviceName, descMapPtr->flags, i);
  676.     }
  677.     }
  678.     if (numAlloced != descMapCheckPointPtr->numAllocDesc) {
  679.     majorErrors++;
  680.     fprintf(stderr, "%s:DescMap: Bad alloc count; is %d should be %d\n",
  681.             deviceName, numAlloced, descMapCheckPointPtr->numAllocDesc);
  682.  
  683.     }
  684.     return ret;
  685.  
  686. }
  687.  
  688. char *
  689. GetUsageState(entryPtr)
  690.     LfsSegUsageEntry *entryPtr;
  691. {
  692.     if (entryPtr->flags & LFS_SEG_USAGE_DIRTY) 
  693.     return "Dirty";
  694.     if (entryPtr->flags & LFS_SEG_USAGE_CLEAN) 
  695.     return "Clean";
  696.     return "Full";
  697. }
  698.  
  699. /*
  700.  *----------------------------------------------------------------------
  701.  *
  702.  * DiskRead --
  703.  *
  704.  *    Read data from disk.
  705.  *
  706.  * Results:
  707.  *    The number of bytes returned.  -1 if error.
  708.  *
  709.  * Side effects:
  710.  *    None.
  711.  *
  712.  *----------------------------------------------------------------------
  713.  */
  714. int
  715. DiskRead(diskFd, blockOffset, bufferSize, bufferPtr)
  716.     int    diskFd;        /* File descriptor of disk. */
  717.     int    blockOffset;    /* Block offset to start read. */
  718.     char *bufferPtr;    /* Buffer to place data. */
  719.     int     bufferSize;    /* Size of buffer. */
  720. {
  721.     int    status;
  722.     int    blocks;
  723.     char *bufPtr;
  724.  
  725.  
  726.     /*
  727.      * Seek to the start of the blocks to read.
  728.      */
  729.     status = lseek(diskFd, blockOffset*blockSize, L_SET);
  730.     if (status < 0) {
  731.     fprintf(stderr,"%s:", deviceName);
  732.     perror("lseek");
  733.     return status;
  734.     }
  735.     /*
  736.      * Read the blocks handling the case the a request that is not a 
  737.      * multiple number of blocks by reading to a temp buffer and copying.
  738.      */
  739.     blocks = (bufferSize + blockSize-1)/blockSize;
  740.     if (bufferSize != blocks * blockSize) { 
  741.     bufPtr = malloc(blocks*blockSize);
  742.     } else {
  743.     bufPtr = bufferPtr;
  744.     }
  745.     status = read(diskFd, bufPtr, blocks*blockSize);
  746.     if (status != blocks*blockSize) {
  747.     if (status < 0) {
  748.         fprintf(stderr,"%s:", deviceName);
  749.         perror("read device");
  750.         return status;
  751.     }
  752.     fprintf(stderr,"%s:Short read on device %d != %d\n",deviceName,
  753.         status, blocks*blockSize);
  754.     } else {
  755.     status = bufferSize;
  756.     }
  757.     if (bufPtr != bufferPtr) { 
  758.     bcopy(bufPtr, bufferPtr, bufferSize);
  759.     free(bufPtr);
  760.     }
  761.     return status;
  762. }
  763.  
  764. typedef struct StableMem {
  765.     LfsStableMemParams  *paramsPtr;  /* Parameters of stable memory. */
  766.     LfsStableMemCheckPoint *checkpointPtr;  /* Checkpoint pointer. */
  767.     char        *dataPtr;
  768. } StableMem;
  769.  
  770. /*
  771.  *----------------------------------------------------------------------
  772.  *
  773.  * LoadStableMem --
  774.  *
  775.  *    Load a stable memory data structure
  776.  *
  777.  * Results:
  778.  *    A clientdata that can be used to access stable mem.
  779.  *
  780.  * Side effects:
  781.  *    None.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785. static ClientData 
  786. LoadStableMem(diskFd, smemParamsPtr, cpPtr, type)
  787.     int diskFd;    /* Disk of file system. */
  788.     LfsStableMemParams  *smemParamsPtr;  /* Parameters of stable memory. */
  789.     LfsStableMemCheckPoint *cpPtr;  /* Checkpoint pointer. */
  790.     int        type;
  791. {
  792.     int arraySize, i;
  793.     char *startDataPtr, *dataPtr;
  794.     int *blockIndexPtr;
  795.     int blockNum;
  796.     LfsStableMemBlockHdr *hdrPtr;
  797.     StableMem *stableMemPtr;
  798.  
  799.     arraySize = smemParamsPtr->blockSize * smemParamsPtr->maxNumBlocks;
  800.     dataPtr = startDataPtr = malloc(arraySize);
  801.     blockIndexPtr = (int *)(((char *) cpPtr) + sizeof(LfsStableMemCheckPoint));
  802.     for (blockNum = 0; blockNum < cpPtr->numBlocks; blockNum++) {
  803.     unsigned int blockIndex = blockIndexPtr[blockNum];
  804.     if (blockIndex == FSDM_NIL_INDEX) {
  805.         bzero(dataPtr, smemParamsPtr->blockSize);
  806.     } else {
  807.         if (blockIndex+smemParamsPtr->blockSize/blockSize > numBlocks) {
  808.            majorErrors++;
  809.            fprintf(stderr, "%s:StableMem%d:Block %d out of range %d\n",
  810.                 deviceName, smemParamsPtr->memType, 
  811.                 blockNum, blockIndex);
  812.         blockIndex = 0;
  813.         }
  814.         for (i = 0; i < smemParamsPtr->blockSize/blockSize; i++) {
  815.         if (full) { 
  816.             if (blockInfoArray[blockIndex + i].type != UNUSED) {
  817.                 majorErrors++;
  818.             fprintf(stderr, "%s:StableMem%d:Block %d duplicate usage of block %d ",
  819.     
  820.                     deviceName, smemParamsPtr->memType, blockNum, blockIndex + i);
  821.             fprintf(stderr,"Previous use at %s\n",
  822.                      GetOwner(blockIndex + i));
  823.     
  824.             } else {
  825.             blockInfoArray[blockIndex + i].type = type;
  826.             blockInfoArray[blockIndex + i].blockNum = blockNum;
  827.             activeBytesArray[BlockToSegmentNum(blockIndex + i)] +=
  828.                         blockSize;
  829.             }
  830.         } else {
  831.             if (Bit_IsSet(blockIndex + i, usageBitMap)) {
  832.                 majorErrors++;
  833.             fprintf(stderr, "%s:StableMem%d:Block %d duplicate usage of block %d\n",
  834.     
  835.                     deviceName, smemParamsPtr->memType, blockNum, blockIndex + i);
  836.             } else {
  837.             Bit_Set(blockIndex + i, usageBitMap);
  838.             activeBytesArray[BlockToSegmentNum(blockIndex + i)] +=
  839.                         blockSize;
  840.             }
  841.         }
  842.         }
  843.         if (DiskRead(diskFd, blockIndex, 
  844.                   smemParamsPtr->blockSize, dataPtr) != 
  845.         smemParamsPtr->blockSize) { 
  846.         majorErrors++;
  847.         fprintf(stderr, "%s:Can't read desc map block %d\n", deviceName, blockNum);
  848.         }
  849.         hdrPtr = (LfsStableMemBlockHdr *) dataPtr;
  850.         if ((hdrPtr->magic != LFS_STABLE_MEM_BLOCK_MAGIC) || 
  851.             (hdrPtr->memType != smemParamsPtr->memType) ||
  852.         (hdrPtr->blockNum != blockNum)) {
  853.         majorErrors++;
  854.         fprintf(stderr, "%s:Bad stable mem header at %d for memType %d blockNum %d\n"
  855.                 , deviceName, blockIndex, 
  856.                 smemParamsPtr->memType, blockNum);
  857.         }
  858.     }
  859.     dataPtr += smemParamsPtr->blockSize;
  860.     }
  861.     bzero(dataPtr, (smemParamsPtr->maxNumBlocks - cpPtr->numBlocks) * 
  862.             smemParamsPtr->blockSize);
  863.     stableMemPtr = (StableMem *) malloc(sizeof(StableMem));
  864.     stableMemPtr->paramsPtr = smemParamsPtr;
  865.     stableMemPtr->checkpointPtr = cpPtr;
  866.     stableMemPtr->dataPtr = startDataPtr;
  867.     return (ClientData) stableMemPtr;
  868. }
  869. char *
  870. GetStableMemEntry(clientData, entryNumber)
  871.     ClientData clientData;
  872.     int entryNumber;
  873. {
  874.     StableMem *stableMemPtr = (StableMem *) clientData;
  875.     int blockNum, offset;
  876.  
  877.     if ((entryNumber < 0) || 
  878.     (entryNumber >= stableMemPtr->paramsPtr->maxNumEntries)) {
  879.     fprintf(stderr,"Bad stable memory entry number %d\n", entryNumber);
  880.     entryNumber = 0;
  881.     }
  882.     blockNum = entryNumber / stableMemPtr->paramsPtr->entriesPerBlock;
  883.     offset = (entryNumber % stableMemPtr->paramsPtr->entriesPerBlock) * 
  884.         stableMemPtr->paramsPtr->entrySize + 
  885.            sizeof(LfsStableMemBlockHdr);
  886.  
  887.     return stableMemPtr->dataPtr + 
  888.         blockNum * stableMemPtr->paramsPtr-> blockSize + offset;
  889. }
  890. static int
  891. GetStableMemBlockIndex(clientData, blockNum)
  892.     ClientData clientData;
  893.     int blockNum;
  894. {
  895.     StableMem *stableMemPtr = (StableMem *) clientData;
  896.     int *blockIndexPtr;
  897.  
  898.     if ((blockNum < 0) || 
  899.     (blockNum >= stableMemPtr->paramsPtr->maxNumBlocks)) {
  900.     fprintf(stderr,"Bad stable memory block num %d\n", blockNum);
  901.     return FSDM_NIL_INDEX;
  902.     }
  903.     blockIndexPtr = (int *)((char *) (stableMemPtr->checkpointPtr) + sizeof(LfsStableMemCheckPoint));
  904.     return blockIndexPtr[blockNum];
  905. }
  906.  
  907. /*
  908.  *----------------------------------------------------------------------
  909.  *
  910.  * CheckAllFiles --
  911.  *
  912.  *    Check all the files in the system.
  913.  *
  914.  * Results:
  915.  *    None.
  916.  *
  917.  * Side effects:
  918.  *    None.
  919.  *
  920.  *----------------------------------------------------------------------
  921.  */
  922. static void
  923. CheckAllFiles(diskFd)
  924.     int diskFd;
  925. {
  926.     LfsFileDescriptor    *descPtr;
  927.     char *descBuf;
  928.     LfsDescMapEntry *descMapPtr;
  929.     int bufSize, i, j;
  930.  
  931.     bufSize = superBlockPtr->fileLayout.descPerBlock * sizeof(*descPtr);
  932.  
  933. #ifdef notdef
  934.     descBuf = alloca(bufSize);
  935. #else
  936.     descBuf = malloc(bufSize);
  937. #endif
  938.     descMapPtr = DescMapEntry(0);
  939.     if (descMapPtr->flags != LFS_DESC_MAP_ALLOCED) {
  940.     majorErrors++;
  941.     fprintf(stderr,"%s:CheckAllFiles: file 0 not allocated.\n",deviceName);
  942.     }
  943.     descMapPtr = DescMapEntry(1);
  944.     if (descMapPtr->flags != LFS_DESC_MAP_ALLOCED) {
  945.     majorErrors++;
  946.     fprintf(stderr,"%s:CheckAllFiles: file 1 not allocated.\n",deviceName);
  947.     }
  948.     descInfoArray[0].flags = descInfoArray[1].flags = FD_UNREADABLE;
  949.  
  950.     for (i = superBlockPtr->descMap.maxDesc-1; i > 1; i--) {
  951.     descMapPtr = DescMapEntry(i);
  952.     if (descMapPtr->flags != LFS_DESC_MAP_ALLOCED) {
  953.         continue;
  954.     }
  955.     if ((descMapPtr->blockAddress < 0) || 
  956.         (descMapPtr->blockAddress > numBlocks)) {
  957.         majorErrors++;
  958.        fprintf(stderr, "%s:CheckAllFiles: Desc %d address out of range %d\n",
  959.             deviceName, i, descMapPtr->blockAddress);
  960.         descInfoArray[i].flags = FD_UNREADABLE;
  961.         continue;
  962.     }
  963.     if (full) { 
  964.         if ((blockInfoArray[descMapPtr->blockAddress].type != UNUSED) &&
  965.         (blockInfoArray[descMapPtr->blockAddress].type != DESC)) {
  966.         majorErrors++;
  967.         fprintf(stderr, "%s:CheckAllFiles:Desc block for %d duplicate usage of block %d ",
  968.     
  969.                 deviceName, i, descMapPtr->blockAddress);
  970.         fprintf(stderr,"Previous use at %s\n",
  971.                 GetOwner(descMapPtr->blockAddress));
  972.     
  973.         } else {
  974.         blockInfoArray[descMapPtr->blockAddress].type = DESC;
  975.         blockInfoArray[descMapPtr->blockAddress].blockNum = 0;
  976.         activeBytesArray[BlockToSegmentNum(descMapPtr->blockAddress)] +=
  977.                     sizeof(LfsFileDescriptor);
  978.         }
  979.     } else {
  980.         if (Bit_IsSet(descMapPtr->blockAddress, usageBitMap) &&
  981.         Bit_IsClear(descMapPtr->blockAddress, descBlockBitMap)) {
  982.         majorErrors++;
  983.         fprintf(stderr, "%s:CheckAllFiles:Desc block for %d duplicate usage of block %d\n",
  984.     
  985.                 deviceName, i, descMapPtr->blockAddress);
  986.  
  987.         activeBytesArray[BlockToSegmentNum(descMapPtr->blockAddress)] +=
  988.                     sizeof(LfsFileDescriptor);
  989.         Bit_Set(descMapPtr->blockAddress, descBlockBitMap);
  990.         } else {
  991.         Bit_Set(descMapPtr->blockAddress, usageBitMap);
  992.         Bit_Set(descMapPtr->blockAddress, descBlockBitMap);
  993.         activeBytesArray[BlockToSegmentNum(descMapPtr->blockAddress)] +=
  994.                     sizeof(LfsFileDescriptor);
  995.         }
  996.     }
  997.     if (DiskRead(diskFd, descMapPtr->blockAddress, bufSize, descBuf)
  998.             != bufSize) {
  999.         majorErrors++;
  1000.         fprintf(stderr,"%s:CheckAllFiles: Can't read desc for file %d\n",
  1001.                 deviceName,i);
  1002.     }
  1003.     descPtr = (LfsFileDescriptor *)descBuf;
  1004.     for (j = 0; j < superBlockPtr->fileLayout.descPerBlock; j++) {
  1005.         if (!(descPtr->common.flags & FSDM_FD_ALLOC)) {
  1006.         break;
  1007.         }
  1008.         if (descPtr->common.magic != FSDM_FD_MAGIC) {
  1009.         majorErrors++;
  1010.         fprintf(stderr,"%s:CheckAllFiles: Corrupted descriptor block at %d, magic number 0x%x\n", deviceName, descMapPtr->blockAddress, descPtr->common.magic);
  1011.         }
  1012.         if (descPtr->fileNumber == i) {
  1013.         break;
  1014.         }
  1015.         descPtr++;
  1016.     }
  1017.     if ((j >= superBlockPtr->fileLayout.descPerBlock) ||
  1018.         !(descPtr->common.flags & FSDM_FD_ALLOC) ||
  1019.         (descPtr->fileNumber != i)) {
  1020.         majorErrors++;
  1021.         fprintf(stderr,"%s:CheckAllFiles: Can't desc for file %d at %d\n",
  1022.             deviceName,i, descMapPtr->blockAddress);
  1023.         descInfoArray[i].flags = FD_UNREADABLE;
  1024.         continue;
  1025.     } else {
  1026.         descInfoArray[i].flags = FD_ALLOCATED;
  1027.     }
  1028.     if (descPtr->common.fileType == FS_DIRECTORY) {
  1029.         descInfoArray[i].flags |= IS_A_DIRECTORY;
  1030.     }
  1031.     descInfoArray[i].origLinkCount = descPtr->common.numLinks;
  1032.     CheckFile(diskFd, i, descPtr);
  1033.     }
  1034. }
  1035.  
  1036. /*
  1037.  *----------------------------------------------------------------------
  1038.  *
  1039.  * CheckFile --
  1040.  *
  1041.  *    Check a file in the system.
  1042.  *
  1043.  * Results:
  1044.  *    None.
  1045.  *
  1046.  * Side effects:
  1047.  *    None.
  1048.  *
  1049.  *----------------------------------------------------------------------
  1050.  */
  1051. static void
  1052. CheckFile(diskFd, fileNum, descPtr) 
  1053.     int diskFd;
  1054.     int fileNum;
  1055.     LfsFileDescriptor *descPtr;
  1056. {
  1057.     int i;
  1058.  
  1059.     for (i = 0; i < FSDM_NUM_DIRECT_BLOCKS; i++) {
  1060.     if (descPtr->common.direct[i] != FSDM_NIL_INDEX) {
  1061.         if (i * FS_BLOCK_SIZE > descPtr->common.lastByte + 1) {
  1062.         majorErrors++;
  1063.         fprintf(stderr, 
  1064.         "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1065.             deviceName,fileNum, i, descPtr->common.lastByte);
  1066.          continue;
  1067.         }
  1068.         CheckBlock(diskFd, fileNum, descPtr, i, descPtr->common.direct[i]);
  1069.     }
  1070.     }
  1071.     if (descPtr->common.indirect[0] != FSDM_NIL_INDEX) { 
  1072.         if (FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE > 
  1073.             descPtr->common.lastByte + 1) {
  1074.         majorErrors++;
  1075.         fprintf(stderr, 
  1076.         "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1077.             deviceName,fileNum, -1, descPtr->common.lastByte);
  1078.         }
  1079.         CheckIndirectBlock(diskFd, fileNum, descPtr, -1,
  1080.                 descPtr->common.indirect[0]);
  1081.     }
  1082.     if (descPtr->common.indirect[1] != FSDM_NIL_INDEX) { 
  1083.         if (FSDM_NUM_DIRECT_BLOCKS * FS_BLOCK_SIZE + 
  1084.             FS_BLOCK_SIZE * FS_BLOCK_SIZE/4 > 
  1085.             descPtr->common.lastByte + 1) {
  1086.         majorErrors++;
  1087.         fprintf(stderr, 
  1088.     "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1089.             deviceName, fileNum, -2, descPtr->common.lastByte);
  1090.         }
  1091.         CheckIndirectBlock(diskFd, fileNum, descPtr, -2, 
  1092.                 descPtr->common.indirect[1]);
  1093.     }
  1094.     if (descPtr->common.indirect[2] != FSDM_NIL_INDEX) { 
  1095.         majorErrors++;
  1096.         fprintf(stderr, 
  1097.     "%s:CheckFile: File %d has a non-NIL block %d after lastByte %d.\n",
  1098.             deviceName, fileNum, -3, descPtr->common.lastByte);
  1099.     }
  1100. }
  1101.  
  1102.  
  1103. /*
  1104.  *----------------------------------------------------------------------
  1105.  *
  1106.  * CheckIndirectBlock --
  1107.  *
  1108.  *    Check an indirect block of a file..
  1109.  *
  1110.  * Results:
  1111.  *    None.
  1112.  *
  1113.  * Side effects:
  1114.  *    None.
  1115.  *
  1116.  *----------------------------------------------------------------------
  1117.  */
  1118.  
  1119. static void
  1120. CheckIndirectBlock(diskFd, fileNum, descPtr, blockNum, blockAddress)
  1121.     int diskFd;
  1122.     int fileNum;
  1123.     LfsFileDescriptor *descPtr;
  1124.     int blockNum;
  1125.     int    blockAddress;
  1126. {
  1127.     int  i;
  1128.     int blockPtrs[FS_BLOCK_SIZE/4];
  1129.  
  1130.  
  1131.  
  1132.     CheckBlock(diskFd, fileNum, descPtr, blockNum, blockAddress);
  1133.     if (DiskRead(diskFd, blockAddress, FS_BLOCK_SIZE, (char *)blockPtrs)
  1134.         != FS_BLOCK_SIZE) {
  1135.     majorErrors++;
  1136.     fprintf(stderr,"%s:CheckIndirectBlock: Can't read block %d of file %d.\n",
  1137.                 deviceName, blockNum, fileNum);
  1138.     return;
  1139.  
  1140.     }
  1141.     if ((blockNum == -1) || (blockNum < -3)) { 
  1142.     int start;
  1143.     if (blockNum == -1) {
  1144.         start = FSDM_NUM_DIRECT_BLOCKS;
  1145.     } else {
  1146.         start = FSDM_NUM_DIRECT_BLOCKS + (FS_BLOCK_SIZE/4) + 
  1147.                  (FS_BLOCK_SIZE/4) * 
  1148.                  (-blockNum - (FSDM_NUM_INDIRECT_BLOCKS+1));
  1149.     }
  1150.     for (i = 0; i < FS_BLOCK_SIZE/4; i++) {
  1151.         if (blockPtrs[i] != FSDM_NIL_INDEX) { 
  1152.         CheckBlock(diskFd, fileNum, descPtr,
  1153.                start + i,blockPtrs[i]);
  1154.         }
  1155.     }
  1156.     return;
  1157.     } 
  1158.     if (blockNum == -2) {
  1159.     for (i = 0; i < FS_BLOCK_SIZE/4; i++) {
  1160.         if (blockPtrs[i] != FSDM_NIL_INDEX) { 
  1161.         CheckIndirectBlock(diskFd, fileNum, descPtr,
  1162.                 - i  - (FSDM_NUM_INDIRECT_BLOCKS+1),blockPtrs[i]);
  1163.         }
  1164.     }
  1165.     return;
  1166.     }
  1167.     majorErrors++;
  1168.     fprintf(stderr,"%s:CheckIndirectBlock: Bad block number %d for file %d\n",
  1169.             deviceName, blockNum, fileNum);
  1170. }
  1171.  
  1172.  
  1173. /*
  1174.  *----------------------------------------------------------------------
  1175.  *
  1176.  * CheckFile --
  1177.  *
  1178.  *    Check a block of a file.
  1179.  *
  1180.  * Results:
  1181.  *    None.
  1182.  *
  1183.  * Side effects:
  1184.  *    None.
  1185.  *
  1186.  *----------------------------------------------------------------------
  1187.  */
  1188. static void
  1189. CheckBlock(diskFd, fileNum, descPtr, blockNum, blockAddress)
  1190.     int diskFd;
  1191.     int fileNum;
  1192.     LfsFileDescriptor *descPtr;
  1193.     int blockNum;
  1194.     int    blockAddress;
  1195. {
  1196.     int j;
  1197.     int sizeInBlocks;
  1198.  
  1199.  
  1200.     sizeInBlocks = FS_BLOCK_SIZE/blockSize;
  1201.     if (blockNum >= 0) { 
  1202.     if ((blockNum+1) * FS_BLOCK_SIZE > descPtr->common.lastByte + 1) {
  1203.         int size;
  1204.         size = descPtr->common.lastByte - FS_BLOCK_SIZE*blockNum +  1;
  1205.          sizeInBlocks = (size + blockSize - 1)/blockSize;
  1206.      }
  1207.     }
  1208.  
  1209.     if ((blockAddress < 0) || 
  1210.     (blockAddress+sizeInBlocks > numBlocks)) {
  1211.     majorErrors++;
  1212.     fprintf(stderr, "%s:CheckFile: file %d block %d is out of range %d\n",
  1213.         deviceName, fileNum, blockNum, blockAddress);
  1214.     return;
  1215.     }
  1216.     for (j = 0; j < sizeInBlocks; j++) {
  1217.     if (full) { 
  1218.         if (blockInfoArray[blockAddress+j].type != UNUSED) {
  1219.         majorErrors++;
  1220.         fprintf(stderr, 
  1221.         "%s:CheckFile:file %d block %d duplicate usage of block %d ",
  1222.             deviceName,
  1223.     
  1224.                 fileNum, blockNum, blockAddress + j);
  1225.         fprintf(stderr,"Previous use at %s\n", 
  1226.                     GetOwner(blockAddress + j));
  1227.         } else {
  1228.         blockInfoArray[blockAddress + j].type = FILE;
  1229.         blockInfoArray[blockAddress + j].fileNum = fileNum;
  1230.         blockInfoArray[blockAddress + j].blockNum = blockNum;
  1231.         }
  1232.     } else {
  1233.         if (Bit_IsSet(blockAddress+j, usageBitMap)) {
  1234.         majorErrors++;
  1235.         fprintf(stderr, 
  1236.         "%s:CheckFile:file %d block %d duplicate usage of block %d\n",
  1237.             deviceName,
  1238.                 fileNum, blockNum, blockAddress + j);
  1239.         } else {
  1240.         Bit_Set(blockAddress+j, usageBitMap);
  1241.         }
  1242.     }
  1243.     }
  1244.     activeBytesArray[BlockToSegmentNum(blockAddress)] 
  1245.             += blockSize*sizeInBlocks;
  1246. }
  1247.  
  1248. /*
  1249.  *----------------------------------------------------------------------
  1250.  *
  1251.  * CheckUsageArray --
  1252.  *
  1253.  *    Check the segment usage array.
  1254.  *
  1255.  * Results:
  1256.  *    None.
  1257.  *
  1258.  * Side effects:
  1259.  *    None.
  1260.  *
  1261.  *----------------------------------------------------------------------
  1262.  */
  1263. static void
  1264. CheckUsageArray(diskFd)
  1265. int diskFd;
  1266. {
  1267.     int segNo;
  1268.     LfsSegUsageEntry *usageArrayPtr;
  1269.  
  1270.     for (segNo = 0; segNo < superBlockPtr->usageArray.numberSegments; 
  1271.     segNo++) {
  1272.     usageArrayPtr = UsageArrayEntry(segNo);
  1273.     if (usageArrayPtr->flags == LFS_SEG_USAGE_CLEAN) {
  1274.         if (activeBytesArray[segNo] != 0) {
  1275.         majorErrors++;
  1276.         fprintf(stderr, "%s:Clean segment %d with activeBytes %d\n",
  1277.             deviceName,segNo, activeBytesArray[segNo]);
  1278.         }
  1279.         continue;
  1280.     }
  1281.     if (usageArrayPtr->activeBytes != activeBytesArray[segNo]) {
  1282.         if (usageArrayPtr->activeBytes < activeBytesArray[segNo]) { 
  1283.             majorErrors++;
  1284.          } else {
  1285.             minorErrors++;
  1286.          }
  1287.         fprintf(stderr,"%s:CheckUsageArray: Active bytes for seg %d is wrong; is %d should be %d\n", deviceName, segNo, usageArrayPtr->activeBytes, 
  1288.             activeBytesArray[segNo]);
  1289.     }
  1290.     }
  1291. }
  1292.  
  1293. /*
  1294.  *----------------------------------------------------------------------
  1295.  *
  1296.  * CheckSummaryRegions --
  1297.  *
  1298.  *    Check the segment summary regions.
  1299.  *
  1300.  * Results:
  1301.  *    None.
  1302.  *
  1303.  * Side effects:
  1304.  *    None.
  1305.  *
  1306.  *----------------------------------------------------------------------
  1307.  */
  1308. static void
  1309. CheckSummaryRegions(diskFd)
  1310. int diskFd;
  1311. {
  1312.     int segNo, startAddr, blockOffset;
  1313.     char *summaryLimitPtr, *summaryPtr;
  1314.     LfsSegSummary *segSummaryPtr;
  1315.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1316.     Seg    *segPtr;
  1317.  
  1318.     for (segNo = 0; segNo < superBlockPtr->usageArray.numberSegments; 
  1319.     segNo++) {
  1320.     segPtr = SegInit(diskFd, segNo);
  1321.     startAddr = SegStartAddr(segPtr) + segPtr->segSizeInBlocks;
  1322.     blockOffset = 1; 
  1323.     do { 
  1324.         segSummaryPtr = (LfsSegSummary *) 
  1325.             SegFetchBlock(segPtr, blockOffset-1, blockSize);
  1326.         if (segSummaryPtr->size == 0) {
  1327.         SegReleaseBlock(segPtr, (char *) segSummaryPtr);
  1328.         break;
  1329.         }
  1330.         if (segSummaryPtr->magic != LFS_SEG_SUMMARY_MAGIC) {
  1331.         majorErrors++;
  1332.         fprintf(stderr,"%s: Bad magic number 0x%x for summary region of segment %d\n", deviceName, segSummaryPtr->magic, segNo);
  1333.         SegReleaseBlock(segPtr, (char *) segSummaryPtr);
  1334.         break;
  1335.         }
  1336.         summaryLimitPtr = (char *) segSummaryPtr + segSummaryPtr->size;
  1337.         summaryPtr = (char *) (segSummaryPtr + 1);
  1338.         while (summaryPtr < summaryLimitPtr) {
  1339.            segSummaryHdrPtr = (LfsSegSummaryHdr *) summaryPtr;
  1340.            if (segSummaryHdrPtr->lengthInBytes == 0) {
  1341.             break;
  1342.            }
  1343.            switch (segSummaryHdrPtr->moduleType) { 
  1344.            case LFS_SEG_USAGE_MOD:
  1345.           CheckSegUsageSummary(diskFd, segPtr, startAddr - blockOffset, blockOffset, 
  1346.                     segSummaryHdrPtr);
  1347.            break;
  1348.            case LFS_DESC_MAP_MOD:
  1349.           CheckDescMapSummary(diskFd, segPtr, startAddr - blockOffset, blockOffset, 
  1350.                     segSummaryHdrPtr);
  1351.            break;
  1352.            case LFS_FILE_LAYOUT_MOD:
  1353.           CheckFileLayoutSummary(diskFd, segPtr,startAddr - blockOffset, blockOffset, 
  1354.                     segSummaryHdrPtr);
  1355.             break;
  1356.            default: {
  1357.             fprintf(stderr,"%s:CheckSummary: Unknown module type %d at %d, Size %d Blocks %d\n",
  1358.                 deviceName, segSummaryHdrPtr->moduleType, startAddr - blockOffset, segSummaryHdrPtr->lengthInBytes, segSummaryHdrPtr->numDataBlocks);
  1359.             break;
  1360.             }
  1361.            }
  1362.            summaryPtr += segSummaryHdrPtr->lengthInBytes;
  1363.            blockOffset += segSummaryHdrPtr->numDataBlocks;
  1364.        }
  1365.        SegReleaseBlock(segPtr, (char *) segSummaryPtr);
  1366.        blockOffset = segSummaryPtr->nextSummaryBlock;
  1367.     } while( blockOffset != -1);
  1368.     SegRelease(segPtr);
  1369.     }
  1370. }
  1371.  
  1372. /*
  1373.  *----------------------------------------------------------------------
  1374.  *
  1375.  * CheckSegUsageSummary --
  1376.  *
  1377.  *    Check the segment summary regions for the seg usage map.
  1378.  *
  1379.  * Results:
  1380.  *    None.
  1381.  *
  1382.  * Side effects:
  1383.  *    None.
  1384.  *
  1385.  *----------------------------------------------------------------------
  1386.  */
  1387. static void
  1388. CheckSegUsageSummary(diskFd, segPtr, startAddress, offset, segSummaryHdrPtr) 
  1389.     int diskFd;
  1390.     Seg *segPtr;
  1391.     int startAddress;
  1392.     int offset;
  1393.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1394. {
  1395.     int blocks, *blockArray, i, startAddr, fsBlocks, j;
  1396.  
  1397.     fsBlocks = superBlockPtr->usageArray.stableMem.blockSize/blockSize;
  1398.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  1399.                 sizeof(int);
  1400.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  1401.     majorErrors++;
  1402.     fprintf(stderr,"%s:CheckSegUsageSummary: Wrong block count; is %d should be %s\n", deviceName, blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  1403.     }
  1404.     blockArray = (int *) (segSummaryHdrPtr + 1);
  1405.     for (i = 0; i < blocks; i++) {
  1406.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  1407.     if ((blockArray[i] < 0) || 
  1408.         (blockArray[i] > superBlockPtr->usageArray.stableMem.maxNumBlocks)){
  1409.         majorErrors++;
  1410.        fprintf(stderr,"%s:CheckSegUsageSummary: Bad block number %d at %d\n",
  1411.             deviceName,blockArray[i], startAddr);
  1412.         continue;
  1413.     }
  1414.     for (j = 0; j < fsBlocks; j++) { 
  1415.         if (UsageArrayBlockIndex(blockArray[i]) != startAddr) {
  1416.         if (full) { 
  1417.             if (blockInfoArray[startAddr + j].type != UNUSED) {
  1418.             majorErrors++;
  1419.             fprintf(stderr,"%s:CheckSegUsageSummary: Summary wrong. Not current block %d at %d in use by %s\n", deviceName, blockArray[i], startAddr + j,
  1420.                 GetOwner(startAddr + j));
  1421.              }
  1422.          } else {
  1423.             if (Bit_IsSet(startAddr + j, usageBitMap)) {
  1424.             majorErrors++;
  1425.             fprintf(stderr,"%s:CheckSegUsageSummary: Summary wrong. Not current block %d at %d\n", deviceName, blockArray[i], startAddr + j);
  1426.              }
  1427.          }
  1428.         } else {
  1429.         if (full) { 
  1430.             if ((blockInfoArray[startAddr + j].type != USAGE_ARRAY) ||
  1431.             (blockInfoArray[startAddr + j].blockNum != blockArray[i])) {
  1432.             majorErrors++;
  1433.             fprintf(stderr,"%s:CheckSegUsageSummary: Summary wrong. Current block %d at %d in use by %s\n", deviceName, blockArray[i], startAddr + j,
  1434.                 GetOwner(startAddr + j));
  1435.              }
  1436.              blockInfoArray[startAddr + j].found = TRUE;
  1437.            } else { 
  1438.            if (Bit_IsClear(startAddr + j, usageBitMap)) {
  1439.             fprintf(stderr,"%s:CheckSegUsageSummary: Summary wrong. Current block %d at %d\n", deviceName, blockArray[i], startAddr + j);
  1440.            }
  1441.            Bit_Set(startAddr + j, foundBitMap);
  1442.            }
  1443.         }
  1444.     }
  1445.     }
  1446.  
  1447. }
  1448.  
  1449. /*
  1450.  *----------------------------------------------------------------------
  1451.  *
  1452.  * CheckSegUsageSummary --
  1453.  *
  1454.  *    Check the segment summary regions for the seg usage map.
  1455.  *
  1456.  * Results:
  1457.  *    None.
  1458.  *
  1459.  * Side effects:
  1460.  *    None.
  1461.  *
  1462.  *----------------------------------------------------------------------
  1463.  */
  1464. static void
  1465. CheckDescMapSummary(diskFd, segPtr, startAddress, offset, segSummaryHdrPtr) 
  1466.     int diskFd;
  1467.     Seg *segPtr;
  1468.     int startAddress;
  1469.     int offset;
  1470.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1471. {
  1472.     int blocks, *blockArray, i, startAddr, fsBlocks, j;
  1473.  
  1474.     fsBlocks = superBlockPtr->descMap.stableMem.blockSize/blockSize;
  1475.     blocks = (segSummaryHdrPtr->lengthInBytes - sizeof(LfsSegSummaryHdr)) /
  1476.                 sizeof(int);
  1477.     if (blocks * fsBlocks != segSummaryHdrPtr->numDataBlocks) {
  1478.     majorErrors++;
  1479.     fprintf(stderr,"%s:CheckDescMapSummary: Wrong block count; is %d should be %s\n", deviceName,blocks * fsBlocks, segSummaryHdrPtr->numDataBlocks);
  1480.     }
  1481.     blockArray = (int *) (segSummaryHdrPtr + 1);
  1482.     for (i = 0; i < blocks; i++) {
  1483.     startAddr = startAddress - i * fsBlocks - fsBlocks;
  1484.     if ((blockArray[i] < 0) || 
  1485.         (blockArray[i] > superBlockPtr->descMap.stableMem.maxNumBlocks)){
  1486.         majorErrors++;
  1487.        fprintf(stderr,"%s:CheckDescMapSummary: Bad block number %d at %d\n",
  1488.             deviceName,blockArray[i], startAddr);
  1489.         continue;
  1490.     }
  1491.     for (j = 0; j < fsBlocks; j++) { 
  1492.         if (DescMapBlockIndex(blockArray[i]) != startAddr) {
  1493.         if (full) { 
  1494.             if (blockInfoArray[startAddr + j].type != UNUSED) {
  1495.             majorErrors++;
  1496.             fprintf(stderr,"%s:CheckDescMapSummary: Summary wrong. Not current block %d at %d in use by %s\n", deviceName,blockArray[i], startAddr + j,
  1497.                  GetOwner(startAddr + j));
  1498.              }
  1499.          } else {
  1500.             if (Bit_IsSet(startAddr + j, usageBitMap)) {
  1501.             majorErrors++;
  1502.             fprintf(stderr,"%s:CheckDescMapSummary: Summary wrong. Not current block %d at %d\n", deviceName,blockArray[i], startAddr + j);
  1503.              }
  1504.          }
  1505.         } else {
  1506.         if (full) { 
  1507.             if ((blockInfoArray[startAddr + j].type != DESC_MAP) ||
  1508.             (blockInfoArray[startAddr + j].blockNum != blockArray[i])) {
  1509.             majorErrors++;
  1510.             fprintf(stderr,"%s:CheckDescMapSummary: Summary wrong. Current block %d at %d in use by %s\n", deviceName, blockArray[i], startAddr + j,
  1511.                  GetOwner(startAddr + j));
  1512.              }
  1513.              blockInfoArray[startAddr + j].found = TRUE;
  1514.          } else {
  1515.              if (Bit_IsClear(startAddr + j, usageBitMap)) {
  1516.             majorErrors++;
  1517.             fprintf(stderr,"%s:CheckDescMapSummary: Summary wrong. Current block %d at %d\n", deviceName, blockArray[i], startAddr + j);
  1518.              }
  1519.              Bit_Set(startAddr + j, foundBitMap);
  1520.          }
  1521.  
  1522.         }
  1523.     }
  1524.     }
  1525.  
  1526. }
  1527.  
  1528. /*
  1529.  *----------------------------------------------------------------------
  1530.  *
  1531.  * CheckFileLayoutSummary --
  1532.  *
  1533.  *    Check the segment summary regions for the file layout code.
  1534.  *
  1535.  * Results:
  1536.  *    None.
  1537.  *
  1538.  * Side effects:
  1539.  *    None.
  1540.  *
  1541.  *----------------------------------------------------------------------
  1542.  */
  1543. static void
  1544. CheckFileLayoutSummary(diskFd, segPtr, startAddr, offset, segSummaryHdrPtr) 
  1545.     int diskFd;
  1546.     Seg  *segPtr;
  1547.     int startAddr;
  1548.     int offset;
  1549.     LfsSegSummaryHdr *segSummaryHdrPtr;
  1550. {
  1551.     char *summaryPtr, *limitPtr;
  1552.     int descMapBlocks;
  1553.     int startAddress, j, ssize;
  1554.     LfsDescMapEntry *descMapPtr;
  1555.  
  1556.     ssize = superBlockPtr->usageArray.segmentSize;
  1557.  
  1558.  
  1559.     startAddress = startAddr;
  1560.     descMapBlocks = superBlockPtr->descMap.stableMem.blockSize/blockSize;
  1561.     summaryPtr = (char *) (segSummaryHdrPtr + 1);
  1562.     limitPtr = summaryPtr + segSummaryHdrPtr->lengthInBytes - 
  1563.             sizeof(LfsSegSummaryHdr);
  1564.     while (summaryPtr < limitPtr) {
  1565.     switch (*(unsigned short *) summaryPtr) {
  1566.     case LFS_FILE_LAYOUT_DESC: {
  1567.         int        fileNumber;
  1568.         int        slot;
  1569.         LfsFileDescriptor    *descPtr;
  1570.         descPtr = (LfsFileDescriptor *) SegFetchBlock(segPtr, offset, 
  1571.                         descMapBlocks*blockSize);
  1572.         offset += descMapBlocks;
  1573.         startAddress -= descMapBlocks;
  1574.         for (slot = 0; slot < superBlockPtr->fileLayout.descPerBlock; 
  1575.         slot++) {
  1576.         int addr;
  1577.         /*
  1578.          * The descriptor block is terminated by an unallocated
  1579.          * descriptor.
  1580.          */
  1581.         if (!(descPtr[slot].common.flags & FSDM_FD_ALLOC)) {
  1582.             break;
  1583.         }
  1584.         addr = startAddress + (slot * sizeof(LfsFileDescriptor))/
  1585.                         blockSize;
  1586.         fileNumber = descPtr[slot].fileNumber;
  1587.         if ((fileNumber < 0) || 
  1588.             (fileNumber >= superBlockPtr->descMap.maxDesc)) {
  1589.             majorErrors++;
  1590.            fprintf(stderr,"%s:CheckFileLayoutSummary: bad file number %d in desc block at %d\n", deviceName, fileNumber, startAddress);
  1591.            continue;
  1592.         }
  1593.         if (full) { 
  1594.             if ((blockInfoArray[addr].type != DESC) &&
  1595.             (blockInfoArray[addr].type != UNUSED)) {
  1596.             majorErrors++;
  1597.             fprintf(stderr,"%s:CheckFileLayoutSummary: Desc block at %d overlaps %s\n", deviceName, addr, GetOwner(addr));
  1598.             }
  1599.             blockInfoArray[addr].found = TRUE;
  1600.         } else {
  1601.             Bit_Set(addr, foundBitMap);
  1602.         }
  1603.          }
  1604.         /*
  1605.          * Skip over the summary bytes describing this block. 
  1606.          */
  1607.         summaryPtr += sizeof(LfsFileLayoutDesc);
  1608.         SegReleaseBlock(segPtr, (char *) descPtr);
  1609.         break;
  1610.     }
  1611.     case LFS_FILE_LAYOUT_DATA: {
  1612.         int    *blockArray;
  1613.         int              i;
  1614.         LfsFileLayoutSummary *fileSumPtr;
  1615.         int firstBlock;
  1616.         Boolean dead;
  1617.         /*
  1618.          * We ran into a data block. If it is still alive bring it into
  1619.          * the cache. 
  1620.          */
  1621.          fileSumPtr = (LfsFileLayoutSummary *) summaryPtr;
  1622.         if ((fileSumPtr->fileNumber < 0) || 
  1623.         (fileSumPtr->fileNumber >= superBlockPtr->descMap.maxDesc)) {
  1624.         majorErrors++;
  1625.            fprintf(stderr,"%s:CheckFileLayoutSummary: bad file number %d at %d\n", deviceName, fileSumPtr->fileNumber, startAddress);
  1626.            goto out;
  1627.         }
  1628.          /*
  1629.           * Liveness check.   First see if the version number is
  1630.           * the same and the file is still allocated.
  1631.           */
  1632.          descMapPtr = DescMapEntry(fileSumPtr->fileNumber);
  1633.          if ((descMapPtr->flags != LFS_DESC_MAP_ALLOCED) || 
  1634.          (descMapPtr->truncVersion != fileSumPtr->truncVersion)) {
  1635.         dead = TRUE;
  1636.         } else {
  1637.         dead = FALSE;
  1638.         }
  1639.  
  1640.         /*
  1641.          * For each block ... 
  1642.          */
  1643.         blockArray = (int *)(summaryPtr + sizeof(LfsFileLayoutSummary));
  1644.         firstBlock = fileSumPtr->numBlocks -
  1645.          (fileSumPtr->numDataBlocks-1) * FS_BLOCK_SIZE/blockSize;
  1646.         for (i = 0; i < fileSumPtr->numDataBlocks; i++) {
  1647.         int addr, blocks;
  1648.  
  1649.         addr = startAddress - i*FS_BLOCK_SIZE/blockSize - firstBlock;
  1650.         blocks = (i == 0) ? firstBlock : (FS_BLOCK_SIZE/blockSize);
  1651.         for (j = 0; j < blocks ; j++) { 
  1652.             if (dead) {
  1653.             if (full) { 
  1654.                 if (blockInfoArray[addr+j].type != UNUSED) {
  1655.                 majorErrors++;
  1656.                 fprintf(stderr,"%s:CheckFileLayoutSummary: Dead block %d of file %d in use at %d, used by %s\n", 
  1657.                 deviceName,
  1658.                 blockArray[i], fileSumPtr->fileNumber, addr+j,
  1659.                 GetOwner(addr + j));
  1660.                  }
  1661.              } else {
  1662.                  if (Bit_IsSet(addr+j, usageBitMap)) {
  1663.                 majorErrors++;
  1664.                 fprintf(stderr,"%s:CheckFileLayoutSummary: Dead block %d of file %d in use at %d\n", 
  1665.                 deviceName,
  1666.                 blockArray[i], fileSumPtr->fileNumber, addr+j);
  1667.                  }
  1668.              }
  1669.             } else {
  1670.             if (full) { 
  1671.                 if (!((blockInfoArray[addr+j].type == UNUSED) ||
  1672.                 ((blockInfoArray[addr+j].type == FILE) &&
  1673.                 (blockInfoArray[addr+j].fileNum == 
  1674.                         fileSumPtr->fileNumber) &&
  1675.                 (blockInfoArray[addr+j].blockNum == blockArray[i])))){
  1676.                 majorErrors++;
  1677.                 fprintf(stderr,"%s:CheckFileLayoutSummary: Block %d of file %d in use at %d, used by %s\n", 
  1678.                 deviceName,
  1679.                 blockArray[i], fileSumPtr->fileNumber, addr+j,
  1680.                 GetOwner(addr + j));
  1681.                  } else {
  1682.                  blockInfoArray[addr+j].found = TRUE;
  1683.                  }
  1684.             } else {
  1685.                 Bit_Set(addr+j, foundBitMap);
  1686.             }
  1687.             }
  1688.         }
  1689.         }
  1690.         out:
  1691.         startAddress = startAddress - fileSumPtr->numBlocks;
  1692.         offset += fileSumPtr->numBlocks;
  1693.         summaryPtr += sizeof(LfsFileLayoutSummary) + 
  1694.                 fileSumPtr->numDataBlocks * sizeof(int); 
  1695.         break;
  1696.       }
  1697.  
  1698.     case LFS_FILE_LAYOUT_DIR_LOG: {
  1699.         LfsFileLayoutLog    *logSumPtr;
  1700.         int            numBlocks;
  1701.         int            i,j, addr, blocks;
  1702.         LfsDirOpLogBlockHdr *hdrPtr = (LfsDirOpLogBlockHdr *) NIL;
  1703.  
  1704.         /* 
  1705.          * Directory log info is not needed during clean so we 
  1706.          * just skip over it.
  1707.          */
  1708.          logSumPtr = (LfsFileLayoutLog *) summaryPtr;
  1709.          summaryPtr = summaryPtr + sizeof(LfsFileLayoutLog);
  1710.          numBlocks = logSumPtr->numBlocks;
  1711.          addr = startAddress;
  1712.          for (i = 0; i < logSumPtr->numDataBlocks; i++) {
  1713.         if (numBlocks > FS_BLOCK_SIZE/blockSize) {
  1714.             blocks = FS_BLOCK_SIZE/blockSize;
  1715.         } else {
  1716.             blocks = numBlocks;
  1717.         }
  1718.  
  1719.             hdrPtr = (LfsDirOpLogBlockHdr *)
  1720.              SegFetchBlock(segPtr, offset, blocks*blockSize);
  1721.         addr -= blocks;
  1722.         offset += blocks;
  1723.         if (hdrPtr->magic != LFS_DIROP_LOG_MAGIC) {
  1724.             fprintf(stderr,"Bad dir op log magic number.\n");
  1725.         }
  1726.         if (showDirLog) { 
  1727.             ShowDirLogBlock(hdrPtr, addr);
  1728.         }
  1729.         for (j = 0; j < blocks; j++) {
  1730.             if (full) { 
  1731.             if (blockInfoArray[addr+j].type != UNUSED) {
  1732.                 majorErrors++;
  1733.                 fprintf(stderr,"%s:CheckFileLayoutSummary: Log block in use at %d, used by %s\n", 
  1734.                 deviceName,
  1735.                 addr+j,
  1736.                 GetOwner(addr + j));
  1737.             }
  1738.             blockInfoArray[addr+j].type = DIRLOG;
  1739.             blockInfoArray[addr+j].found = TRUE;
  1740.             } else {
  1741.             if (Bit_IsSet(addr+j, usageBitMap)) {
  1742.                 majorErrors++;
  1743.                 fprintf(stderr,"%s:CheckFileLayoutSummary: Log block in use at %d\n", 
  1744.                 deviceName,
  1745.                 addr+j);
  1746.             }
  1747.             Bit_Set(addr+j, usageBitMap);
  1748.             Bit_Set(addr+j, foundBitMap);
  1749.             }
  1750.         }
  1751.         numBlocks -= blocks;
  1752.          }
  1753.  
  1754.          startAddress = startAddress - logSumPtr->numBlocks;
  1755.          if ( hdrPtr != (LfsDirOpLogBlockHdr *) NIL) { 
  1756.          SegReleaseBlock(segPtr, (char *) hdrPtr);
  1757.         }
  1758.          break;
  1759.     }
  1760.     case LFS_FILE_LAYOUT_DBL_INDIRECT: 
  1761.     case LFS_FILE_LAYOUT_INDIRECT: 
  1762.     default: {
  1763.         panic("Unknown type");
  1764.     }
  1765.       }
  1766.     }
  1767.  
  1768. }
  1769. static char *
  1770. GetOwner(blockNum)
  1771.     int blockNum;
  1772. {
  1773.     static char buffer[128];
  1774.  
  1775.     sprintf(buffer, "<%d,%d,%d>", blockInfoArray[blockNum].type,
  1776.                 blockInfoArray[blockNum].fileNum,
  1777.                 blockInfoArray[blockNum].blockNum);
  1778.  
  1779.     return buffer;
  1780. }
  1781.  
  1782. /*
  1783.  *----------------------------------------------------------------------
  1784.  *
  1785.  * PrintSuperBlock --
  1786.  *
  1787.  *    Print super block contents.
  1788.  *
  1789.  * Results:
  1790.  *    None.
  1791.  *
  1792.  * Side effects:
  1793.  *    None.
  1794.  *
  1795.  *----------------------------------------------------------------------
  1796.  */
  1797. static void
  1798. PrintSuperBlock(superBlockPtr)
  1799.     LfsSuperBlock *superBlockPtr;
  1800. {
  1801.     printf("SuperBlock.hdr.version: %d\n", superBlockPtr->hdr.version);
  1802.     printf("SuperBlock.hdr.blockSize: %d\n", 
  1803.                 superBlockPtr->hdr.blockSize);
  1804.     printf("SuperBlock.hdr.maxCheckPointBlocks: %d\n", 
  1805.                 superBlockPtr->hdr.maxCheckPointBlocks);
  1806.     printf("SuperBlock.hdr.checkPointOffset[0]: %d\n", 
  1807.             superBlockPtr->hdr.checkPointOffset[0]);
  1808.     printf("SuperBlock.hdr.checkPointOffset[1]: %d\n", 
  1809.             superBlockPtr->hdr.checkPointOffset[1]);
  1810.     printf("SuperBlock.hdr.logStartOffset: %d\n", 
  1811.             superBlockPtr->hdr.logStartOffset);
  1812.     printf("SuperBlock.hdr.maxNumCacheBlocks: %d\n", 
  1813.             superBlockPtr->hdr.maxNumCacheBlocks);
  1814.     printf("SuperBlock.descMap.version: %d\n", superBlockPtr->descMap.version);
  1815.     printf("SuperBlock.descMap.maxDesc: %d\n", superBlockPtr->descMap.maxDesc);
  1816.     printf("SuperBlock.descMap.stableMem.blockSize: %d\n", 
  1817.             superBlockPtr->descMap.stableMem.blockSize);
  1818.     printf("SuperBlock.descMap.stableMem.maxNumBlocks: %d\n", 
  1819.             superBlockPtr->descMap.stableMem.maxNumBlocks);
  1820.     printf("SuperBlock.usageArray.segmentSize: %d\n", 
  1821.                 superBlockPtr->usageArray.segmentSize);
  1822.     printf("SuperBlock.usageArray.numberSegments: %d\n", 
  1823.                 superBlockPtr->usageArray.numberSegments);
  1824.     printf("SuperBlock.usageArray.minNumClean: %d\n", 
  1825.                 superBlockPtr->usageArray.minNumClean);
  1826.     printf("SuperBlock.usageArray.minFreeBlocks: %d\n", 
  1827.                 superBlockPtr->usageArray.minFreeBlocks);
  1828.     printf("SuperBlock.usageArray.stableMem.blockSize: %d\n", 
  1829.             superBlockPtr->descMap.stableMem.blockSize);
  1830.     printf("SuperBlock.usageArray.stableMem.maxNumBlocks: %d\n", 
  1831.             superBlockPtr->descMap.stableMem.maxNumBlocks);
  1832.     printf("SuperBlock.fileLayout.descPerBlock: %d\n", 
  1833.                 superBlockPtr->fileLayout.descPerBlock);
  1834. }
  1835.  
  1836.  
  1837. /*
  1838.  *----------------------------------------------------------------------
  1839.  *
  1840.  * PrintCheckPointHdr --
  1841.  *
  1842.  *    Print check point header contents.
  1843.  *
  1844.  * Results:
  1845.  *    None.
  1846.  *
  1847.  * Side effects:
  1848.  *    None.
  1849.  *
  1850.  *----------------------------------------------------------------------
  1851.  */
  1852. static void
  1853. PrintCheckPointHdr(headerPtr, region)
  1854.     LfsCheckPointHdr *headerPtr;
  1855.     int region;
  1856. {
  1857.     printf("CheckPointHdr[%d].timestamp: %d\n", region, headerPtr->timestamp);
  1858.     printf("CheckPointHdr[%d].size: %d\n", region, headerPtr->size);
  1859.     printf("CheckPointHdr[%d].version: %d\n", region, headerPtr->version);
  1860.     printf("CheckPointHdr[%d].domainPrefix: %s\n", region, 
  1861.                     headerPtr->domainPrefix);
  1862.     printf("CheckPointHdr[%d].domainNumber: %d\n", region,
  1863.                 headerPtr->domainNumber);
  1864.     printf("CheckPointHdr[%d].attachSeconds: %d\n", region, 
  1865.             headerPtr->attachSeconds);
  1866.     printf("CheckPointHdr[%d].detachSeconds: %d\n", region, 
  1867.             headerPtr->detachSeconds);
  1868.     printf("CheckPointHdr[%d].serverID: %d\n", region, 
  1869.             headerPtr->serverID);
  1870. }
  1871.  
  1872. static void
  1873. ShowDirLogBlock(hdrPtr, addr)
  1874.     LfsDirOpLogBlockHdr *hdrPtr;
  1875.     int addr;
  1876. {
  1877.     LfsDirOpLogEntry *entryPtr, *limitPtr;
  1878.  
  1879.     printf("Dirlog block at %d, size %d\n", addr, hdrPtr->size);
  1880.     limitPtr = (LfsDirOpLogEntry *) (((char *) hdrPtr) + hdrPtr->size);
  1881.     entryPtr = (LfsDirOpLogEntry *) (hdrPtr+1);
  1882.     while (entryPtr < limitPtr) {
  1883.     printf("LogSeqNum %d opFlags 0x%x dirFile %d dirOffset %d linkCount %d\n",
  1884.         entryPtr->hdr.logSeqNum, entryPtr->hdr.opFlags, 
  1885.         entryPtr->hdr.dirFileNumber,
  1886.         entryPtr->hdr.dirOffset, entryPtr->hdr.linkCount);
  1887.     entryPtr->dirEntry.fileName[entryPtr->dirEntry.nameLength] = '\0';
  1888.     printf("    File %d Name %s\n", entryPtr->dirEntry.fileNumber, 
  1889.         entryPtr->dirEntry.fileName);
  1890.     entryPtr = (LfsDirOpLogEntry *) 
  1891.              (((char *)entryPtr) + LFS_DIR_OP_LOG_ENTRY_SIZE(entryPtr));
  1892.     }
  1893.  
  1894. }
  1895.  
  1896. static char *
  1897. FmtTime()
  1898. {
  1899.      struct timeval tim;
  1900.      time_t  timeVal;
  1901.      static char timeBuffer[128];
  1902.  
  1903.      if (gettimeofday(&tim, (struct timezone *) NULL)) {
  1904.      perror("gettimeofday");
  1905.      return "Unknown";
  1906.      }
  1907.      timeVal = tim.tv_sec;
  1908.      (void)strcpy(timeBuffer, ctime(&timeVal) + sizeof("Sun Sep 16 ")-1);
  1909.  
  1910.      sprintf(timeBuffer+sizeof("01:03:52")-1,".%03d", tim.tv_usec/1000);
  1911.      return timeBuffer;
  1912. }
  1913.  
  1914. static Seg *
  1915. SegInit(diskFd, segNumber)
  1916.     int    diskFd;
  1917.     int    segNumber;    /* Segment number to operate on. */
  1918. {
  1919.     static Seg seg;
  1920.     seg.segNo = segNumber;
  1921.     seg.segSizeInBlocks = superBlockPtr->usageArray.segmentSize/blockSize;
  1922.     seg.diskFd = diskFd;
  1923.     return &seg;
  1924. }
  1925.  
  1926. static int
  1927. SegStartAddr(segPtr)
  1928.     Seg    *segPtr;
  1929. {
  1930.     return  segPtr->segNo * segPtr->segSizeInBlocks + 
  1931.             superBlockPtr->hdr.logStartOffset;
  1932. }
  1933. static char *
  1934. SegFetchBlock(segPtr, blockOffset, size)
  1935.     Seg        *segPtr;
  1936.     int        blockOffset;
  1937.     int        size;
  1938. {
  1939.     char *buf;
  1940.     int      startAddr;
  1941.  
  1942.     startAddr = SegStartAddr(segPtr) + segPtr->segSizeInBlocks - blockOffset -
  1943.         size/blockSize;
  1944.     buf = malloc(size);
  1945.  
  1946.     if (DiskRead(segPtr->diskFd, startAddr , size, buf) != size) {
  1947.     fprintf(stderr,"%s:SegFetchBlock: Can't read seg %d offset %d.\n", deviceName, segPtr->segNo, blockOffset);
  1948.     }
  1949.     return buf;
  1950. }
  1951. static void
  1952. SegReleaseBlock(segPtr, memPtr)
  1953.     Seg        *segPtr;
  1954.     char    *memPtr;
  1955. {
  1956.     free(memPtr);
  1957. }
  1958. static void
  1959. SegRelease(segPtr)
  1960.     Seg        *segPtr;
  1961. {
  1962. }
  1963.